package com.java.wechat.service.impl;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.java.wechat.controller.exception.RException;
import com.java.wechat.dao.ChatMsgDao;
import com.java.wechat.dao.FriendsRequestDao;
import com.java.wechat.dao.MyFriendsDao;
import com.java.wechat.dao.UserDao;
import com.java.wechat.entity.FriendsRequest;
import com.java.wechat.entity.MyFriends;
import com.java.wechat.entity.User;
import com.java.wechat.entity.bo.UserBO;
import com.java.wechat.entity.vo.FriendRequestVO;
import com.java.wechat.entity.vo.MyFriendsVO;
import com.java.wechat.entity.vo.UserVO;
import com.java.wechat.enums.MsgActionEnum;
import com.java.wechat.enums.MsgSignFlagEnum;
import com.java.wechat.enums.SearchFriendsStatusEnum;
import com.java.wechat.netty.DataContent;
import com.java.wechat.netty.UserChannelRel;
import com.java.wechat.service.UserService;
import com.java.wechat.util.FastDFSClient;
import com.java.wechat.util.FileUtils;
import com.java.wechat.util.R;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;

import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;


@Service
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService {
	@Autowired
	private Snowflake snowflake;
    @Autowired
    private FastDFSClient fastDFSClient;
    @Autowired
    private MyFriendsDao myFriendsDao;
    @Autowired
    private FriendsRequestDao friendsRequestDao;
    @Autowired
    private ChatMsgDao chatMsgDao;

	@Override
	public Boolean queryUsernameIsExist(String username) {
		User user = this.baseMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUsername, username));
		return user != null;
	}

	@Override
	public User queryUserForLogin(String username, String password) {
		password = SecureUtil.md5(password);
		return this.baseMapper.selectOne(new LambdaQueryWrapper<User>()
				.eq(User::getUsername, username)
				.eq(User::getPassword, password));
	}

	@Override
	public User saveUser(User user) {
		String userId = snowflake.nextIdStr();
		// 为每个用户生成一个唯一的二维码
		String qrCodePath = userId + "qrcode.png";
		// muxin_qrcode:[username]
		QrCodeUtil.generate("qrcode:" + user.getUsername(), 300, 300, new File(qrCodePath));
		//上传到fdfs
		String path;
		try {
			path = fastDFSClient.uploadFile(new File(qrCodePath));
		} catch (IOException e) {
			e.printStackTrace();
			throw new RException("用户二维码上传失败!");
		}

		//补充用户资料
		user.setId(userId);
		user.setPassword(SecureUtil.md5(user.getPassword()));
		user.setNickname(user.getUsername());
		user.setQrcode(path);
        this.baseMapper.insert(user);
        return user;
	}

	@Override
	public R uploadFaceBase64(UserBO userBO) {
		//获取前端传过来的base64字符串
		String base64Data = userBO.getFaceData();
		String filePath = userBO.getUserId() + ".png";

        Map<String, String> result;
		//转换为文件对象
        try {
            FileUtils.base64ToFile(filePath, base64Data);
            // 上传文件到fastdfs
            result = fastDFSClient.uploadImageAndCrtThumbImage(new File(filePath));
        } catch (Exception e) {
            e.printStackTrace();
            throw new RException("图片上传失败!");
        }

        //更新用户
        User user = this.baseMapper.selectById(userBO.getUserId());
        user.setFaceImageBig(result.get("image"));
        user.setFaceImage(result.get("thumbImage"));
		return updateUser(user);
	}


	public R setNickname(@RequestBody UserBO userBO) {
		User user = this.baseMapper.selectById(userBO.getUserId());
		user.setNickname(userBO.getNickname());
		return updateUser(user);
	}

	@Override
	public Integer preconditionSearchFriends(String myUserId, String friendUsername) {
		//根据查询名称进行搜索
		User user = this.baseMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUsername,friendUsername));

		// 1. 搜索的用户如果不存在，返回[无此用户]
		if (user == null) {
			return SearchFriendsStatusEnum.USER_NOT_EXIST.status;
		}

		// 2. 搜索账号是你自己，返回[不能添加自己]
		if (user.getId().equals(myUserId)) {
			return SearchFriendsStatusEnum.NOT_YOURSELF.status;
		}

		// 3. 搜索的朋友已经是你的好友，返回[该用户已经是你的好友]
		MyFriends myFriends = myFriendsDao.selectOne(new LambdaQueryWrapper<MyFriends>().eq(MyFriends::getMyUserId, myUserId)
				.eq(MyFriends::getMyFriendUserId, user.getId()));
		if (myFriends != null) {
			return SearchFriendsStatusEnum.ALREADY_FRIENDS.status;
		}

		return SearchFriendsStatusEnum.SUCCESS.status;
	}

	@Override
	public void sendFriendRequest(String myUserId, String friendUsername) {

		// 根据用户名把朋友信息查询出来
		User friend = this.baseMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUsername,friendUsername));

		// 1. 查询发送好友请求记录表
		FriendsRequest friendRequest = friendsRequestDao.selectOne(new LambdaQueryWrapper<FriendsRequest>().eq(FriendsRequest::getSendUserId, myUserId)
				.eq(FriendsRequest::getAcceptUserId, friend.getId()));
		if (friendRequest == null) {
			// 2. 如果不是你的好友，并且好友记录没有添加，则新增好友请求记录
			String requestId = snowflake.nextIdStr();
			FriendsRequest request = new FriendsRequest();
			request.setId(requestId);
			request.setSendUserId(myUserId);
			request.setAcceptUserId(friend.getId());
			request.setRequestDateTime(new Date());
			friendsRequestDao.insert(request);
		}
	}

	@Override
	public List<FriendRequestVO> queryFriendRequestList(String userId) {
		return friendsRequestDao.queryFriendRequests(userId);
	}

	@Override
	public void deleteFriendRequest(String sendUserId, String acceptUserId) {
		friendsRequestDao.delete(new LambdaQueryWrapper<FriendsRequest>().eq(FriendsRequest::getSendUserId, sendUserId)
				.eq(FriendsRequest::getAcceptUserId, acceptUserId));
	}

	@Override
	public void passFriendRequest(String sendUserId, String acceptUserId) {
		saveFriends(sendUserId, acceptUserId);
		saveFriends(acceptUserId, sendUserId);
		deleteFriendRequest(sendUserId, acceptUserId);

		Channel sendChannel = UserChannelRel.get(sendUserId);
		if (sendChannel != null) {
			// 使用websocket主动推送消息到请求发起者，更新他的通讯录列表为最新
			DataContent dataContent = new DataContent();
			dataContent.setAction(MsgActionEnum.PULL_FRIEND.type);

			sendChannel.writeAndFlush(new TextWebSocketFrame(String.valueOf(JSONUtil.parse(dataContent))));
		}
	}

	@Override
	public List<MyFriendsVO> queryMyFriends(String userId) {
		return myFriendsDao.queryMyFriends(userId);
	}

	@Override
	public String saveMsg(com.java.wechat.netty.ChatMsg chatMsg) {
		com.java.wechat.entity.ChatMsg msgDB = new com.java.wechat.entity.ChatMsg();
		String msgId = snowflake.nextIdStr();
		msgDB.setId(msgId);
		msgDB.setAcceptUserId(chatMsg.getReceiverId());
		msgDB.setSendUserId(chatMsg.getSenderId());
		msgDB.setCreateTime(new Date());
		msgDB.setSignFlag(MsgSignFlagEnum.unsign.type);
		msgDB.setMsg(chatMsg.getMsg());

		chatMsgDao.insert(msgDB);
		return msgId;
	}

	@Override
	public void updateMsgSigned(List<String> msgIdList) {
		com.java.wechat.entity.ChatMsg chatMsg = new com.java.wechat.entity.ChatMsg();
		chatMsg.setSignFlag(1);
		chatMsgDao.update(chatMsg,
				new LambdaQueryWrapper<com.java.wechat.entity.ChatMsg>().in(com.java.wechat.entity.ChatMsg::getId,msgIdList));
	}

	@Override
	public List<com.java.wechat.entity.ChatMsg> getUnReadMsgList(String acceptUserId) {
		return chatMsgDao.selectList(new LambdaQueryWrapper<com.java.wechat.entity.ChatMsg>().eq(com.java.wechat.entity.ChatMsg::getSignFlag,0)
		.eq(com.java.wechat.entity.ChatMsg::getAcceptUserId,acceptUserId));
	}

	private void saveFriends(String sendUserId, String acceptUserId) {
		MyFriends myFriends = new MyFriends();
		String recordId = snowflake.nextIdStr();
		myFriends.setId(recordId);
		myFriends.setMyFriendUserId(acceptUserId);
		myFriends.setMyUserId(sendUserId);
		myFriendsDao.insert(myFriends);
	}

	/**
	 * 更新用户,返回userVO
	 */
	private R updateUser(User user) {
		this.updateById(user);

		//返回userVO
		UserVO userVO = new UserVO();
		BeanUtils.copyProperties(user,userVO);
		return R.ok().put("data",userVO);
	}


}